home *** CD-ROM | disk | FTP | other *** search
- Subject: v08i059: A Unix/PC virtual terminal package, Part01/02
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: Guido van Rossum <seismo!mcvax!guido>
- Mod.sources: Volume 8, Issue 59
- Archive-name: vtrm/Part01
-
- [ This package provides duplicate functionality for Unix and PC
- screen-oriented programs. (Is that sentence in English?)
- A Makefile doesn't make sense, and I guess I'm being nice by
- not sticking to my requirement for a manpage. Comments on that,
- anyone? I have not done anything to or with these programs, other
- than to re-shar them. -r$ ]
-
- As the README file mentions, there is little documentation and no
- test program. Adding all the stuff to make it into a "neat" posting
- would cost me a day or two, which I simply can't spare. I believe that
- it is useful enough in its current state.
- Guido van Rossum, CWI, Amsterdam <guido@mcvax.uucp>
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # If all goes well, you will see the message "End of archive 1 (of 2)."
- # Contents: README p1trm.c trm.h MANIFEST
- PATH=/bin:/usr/bin:/usr/ucb; export PATH
- echo shar: extracting "'README'" '(2381 characters)'
- if test -f 'README' ; then
- echo shar: will not over-write existing file "'README'"
- else
- sed 's/^X//' >README <<'@//E*O*F README//'
- XTHIS IS VTRM
- X============
- X
- XVTRM is a terminal control package, with two implementations: one for Unix
- X(only well-tested on 4.2/4.3 BSD, but supposedly running under System 5
- Xas well, as long as there is a termcap database), and one for MS-DOS, to
- Xbe compiled with the Microsoft C compiler (tested only with version 3.0).
- XThis is a "curses replacement", which does not mean it is a curses
- Xreimplementation: the interface is totally different, only the purpose
- Xis more or less the same: to shield an application program from the
- Xnitty-gritty detail of cursor navigation, inverse video, scrolling, etc.
- XThere are also a few routines for CBREAK-mode input.
- X
- XUNPACKING NOTES
- X
- XThe shars yield five files:
- X README (this file)
- X trm.h (common header file)
- X p1trm.c (MS-DOS version)
- X vtrm.c_1
- X vtrm.c_2
- XThe latter two should be pasted together to get a file named vtrm.c:
- X cat vtrm.c_[12] >vtrm.c
- X
- XAPOLOGY
- X
- XI must apologize for the poor documentation. Most of it has the form of
- Xcomments in the source files (note the "specs" for the entire package at
- Xthe end of vtrm.c). This is a library package but I do not have an
- Xadequate test program for it; I usually test it with one of the two
- Xapplications that use it -- these are too big to include in this posting.
- X
- XFUTURE DIRECTIONS
- X
- XThis version of VTRM is by no means an end point in its development.
- XWork is under way for an implementation that provides the same interface
- Xon the Macintosh. You are invided to engage in implementations for othr
- Xmachines, such as as the Atari ST and the Commodore Amiga. Comments on
- Xthe interface are more than welcome, and should be sent by electronic
- Xmail to guido@mcvax.uucp; this is also the address for bugfixes and
- Xother questions.
- X
- XAUTHORS
- X
- XThis software was written by:
- X
- X Timo Krijnen and Guido van Rossum
- X CWI, dept. AA
- X Kruislaan 413
- X 1089 SJ Amsterdam
- X The Netherlands
- X
- X Electronic mail: timo@mcvax.uucp, guido@mcvax.uucp
- X Phone: ... 20 - 592 4138.
- X
- XCOPYRIGHT
- X
- XThis software is copyright (c) 1986 by Stichting Mathematisch Centrum,
- XAmsterdam, The Netherlands. Its use is allowed freely for
- Xnon-commercial purposes only. Use at your own risk: SMC does not take
- Xresponsibility for the proper functioning of the software or for damage
- Xcaused by its use. Redistribution is allowed for non-commercial
- Xpurposes only, and only unchanged, in its entirety, and including this
- Xcopyright notice.
- @//E*O*F README//
- if test 2381 -ne "`wc -c <'README'`"; then
- echo shar: error transmitting "'README'" '(should have been 2381 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'p1trm.c'" '(21268 characters)'
- if test -f 'p1trm.c' ; then
- echo shar: will not over-write existing file "'p1trm.c'"
- else
- sed 's/^X//' >p1trm.c <<'@//E*O*F p1trm.c//'
- X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- X
- X/*
- X * ibm Pc virtual TeRMinal package.
- X *
- X * An implementation of the VTRM interface for MS-DOS machines.
- X *
- X * This code supports two MODE's of accessing the screen.
- X * The first one (BIOS) will be used, unless the user overwrites this
- X * by setting the SCREEN environment variable.
- X * This variable can also be used to convey a screen size that differs
- X * from the default 25 lines and 80 columns. See below.
- X *
- X * The two modes are:
- X *
- X * 1) IBM BIOS interrupt 10 hex, video io.
- X * (See IBM PC XT Technical Reference 6936833, May 1983,
- X * Appendix A, pages A46-A47).
- X * This is what you really want to use, since it's the only one that
- X * can decently scroll. It cannot insert or delete characters, so
- X * most optimisations from vtrm.c are useless and taken out.
- X * Unfortunately, not every PC-compatible machine supports this BIOS
- X * interrupt, so for these unlucky souls there is the following escape:
- X *
- X * 2) The ANSI.SYS driver.
- X * (See IBM MS-DOS 6936839, Jan 1983, Version 2.00, Chapter 13.)
- X * (Some compatibles don't have a separate ANSI.SYS driver but do the
- X * same escape interpretation by default.)
- X * This works reasonably, apart from scrolling downward, or part of
- X * the screen, which is clumsy.
- X * (The ANSI standard provides an escape sequence for scrolling
- X * but ANSI.SYS does not support it, nor any other way of scrolling.)
- X *
- X * The rest of the interface is the same as described in vtrm.c,
- X * with the following exceptions:
- X * - to ease coding for ansi scrolls, the terminal is supposed to
- X * contain blanks at positions that were not written yet;
- X * the unknown rubbish that is initially on the screen can
- X * only be cleared by the caller by scrolling the whole screen up
- X * by one or more lines;
- X * - the number of lines on the terminal is assumed to be 25;
- X * the number of columns is (1) determined by a BIOS function, or
- X * (2) assumed to be 80 for ANSI;
- X * the user can overwrite this by setting the environment variable:
- X *
- X * SET SCREEN=BIOS x y
- X * or
- X * SET SCREEN=ANSI x y
- X *
- X * where x and y are the number of lines and columns respectively.
- X *
- X * The lines and columns of our virtual terminal are numbered
- X * y = {0...lines-1} from top to bottom, and
- X * x = {0...cols-1} from left to right,
- X * respectively.
- X *
- X * The Visible Procedures in this package are as described in vtrm.c.
- X *
- X */
- X
- X/*
- X * Includes and data definitions.
- X */
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <ctype.h>
- X#include <dos.h>
- X
- Xchar *malloc();
- X
- X#include "trm.h"
- X
- X#ifdef lint
- X#define VOID (void)
- X#else
- X#define VOID
- X#endif
- X
- X#define Forward
- X#define Visible
- X#define Hidden static
- X#define Procedure
- X
- Xtypedef short intlet;
- Xtypedef char *string;
- Xtypedef char bool;
- X#define Yes '\1'
- X#define No '\0'
- X#define Undefined (-1)
- X
- X#define Min(a,b) ((a) <= (b) ? (a) : (b))
- X
- X#define MESS(number, text) text
- X
- X#ifdef GFX
- X#include "gfx.h"
- X#endif
- X
- X/* terminal status */
- X
- XHidden int started = No;
- X
- XHidden int scr_mode = 0;
- X#define ANSI 'A'
- X#define BIOS 'B'
- X
- X#define Nlines 25
- X#define Ncols 80
- XHidden int lines = Nlines;
- XHidden int cols = Ncols;
- XHidden int flags = 0;
- X
- X/* current standout mode */
- X#define Off 0
- X#define On 0200
- XHidden int so_mode = Off;
- X
- X/* masks for char's and intlet's */
- X#define NULCHAR '\000'
- X#define CHAR 0177
- X#define SOBIT On
- X#define SOCHAR 0377
- X
- X/* current cursor position */
- XHidden intlet cur_y = Undefined, cur_x = Undefined;
- X
- X/* "line[y][x]" holds the char on the terminal, with the SOBIT.
- X * the SOBIT tells whether the character is standing out.
- X * "lenline[y]" holds the length of the line.
- X * (Partially) empty lines are distinghuished by "lenline[y] < cols".
- X * Unknown chars will be ' ', so the scrolling routines for ANSI
- X * can use "unwritten" chars (with indent > 0 in trmputdata).
- X * To make the optimising compare in putline fail, lenline[y] is initially 0.
- X * The latter implies that if a line is first addressed with trmputdata,
- X * any rubbish that is on the screen beyond the data that gets put, will
- X * remain there.
- X */
- XHidden char **line = 0;
- XHidden intlet *lenline = 0;
- X
- X/* Make the cursor invisible when trmsync() tries to move outside the screen */
- XHidden bool no_cursor = No;
- X
- X/*
- X * Starting, Ending and (fatal) Error.
- X */
- X
- X/*
- X * Initialization call.
- X * Determine terminal mode.
- X * Start up terminal and internal administration.
- X * Return Yes if succeeded, No if trouble (which doesn't apply here).
- X */
- XVisible int
- Xtrmstart(plines, pcols, pflags)
- Xint *plines;
- Xint *pcols;
- Xint *pflags;
- X{
- X static char setup = No;
- X int err;
- X
- X#ifdef TRACE
- Xif (!setup) freopen("TRACE.DAT", "a", stderr);
- Xfprintf(stderr, "\ttrmstart(&li, &co, &fl);\n");
- X#endif
- X
- X if (started)
- X return TE_TWICE;
- X
- X#ifdef GFX
- X if (gfx_mode != TEXT_MODE)
- X gfx_mode= SPLIT_MODE;
- X#endif
- X
- X if (!setup) {
- X err= set_screen_up();
- X if (err != TE_OK)
- X return err;
- X setup = Yes;
- X }
- X
- X err= start_trm(); /* internal administration */
- X if (err != TE_OK)
- X return err;
- X
- X *plines = lines;
- X *pcols = cols;
- X *pflags = flags;
- X
- X set_handler();
- X started = Yes;
- X return TE_OK;
- X}
- X
- XHidden int
- Xset_screen_up()
- X{
- X int height;
- X int width;
- X int get_screen_env();
- X int get_cols();
- X
- X height = width = 0;
- X scr_mode = get_screen_env(&height, &width);
- X
- X switch (scr_mode) {
- X case BIOS:
- X case TE_OK:
- X cols = get_cols();
- X flags = HAS_STANDOUT|CAN_SCROLL;
- X break;
- X case ANSI:
- X flags = HAS_STANDOUT;
- X break;
- X default:
- X return scr_mode; /* Error flag */
- X }
- X
- X /* allow x and y in environment variable SCREEN to override */
- X if (height > 0)
- X lines = height;
- X if (width > 0)
- X cols = width;
- X return TE_OK;
- X}
- X
- XHidden int
- Xget_screen_env(pheight, pwidth)
- X int *pheight, *pwidth;
- X{
- X string s;
- X int mode;
- X char screrr;
- X string getenv();
- X string strip();
- X string skip();
- X
- X screrr = No;
- X s = getenv("SCREEN");
- X if (s == NULL)
- X return BIOS;
- X
- X s = strip(s);
- X switch (*s) {
- X case '\0':
- X return BIOS;
- X case 'a':
- X mode = ANSI;
- X s = skip(s, "ansi");
- X break;
- X case 'A':
- X mode = ANSI;
- X s = skip(s, "ANSI");
- X break;
- X case 'b':
- X mode = BIOS;
- X s = skip(s, "bios");
- X break;
- X case 'B':
- X mode = BIOS;
- X s = skip(s, "BIOS");
- X break;
- X default:
- X mode = BIOS;
- X screrr = Yes;
- X }
- X
- X /* *pheight and *pwidth were set to 0 above */
- X s = strip(s);
- X while (isdigit(*s)) {
- X *pheight = *pheight * 10 + (*s++ - '0');
- X }
- X s = strip(s);
- X while (isdigit(*s)) {
- X *pwidth = *pwidth * 10 + (*s++ -'0');
- X }
- X s = strip(s);
- X if (screrr || *s != '\0')
- X return TE_BADTERM;
- X
- X return mode;
- X}
- X
- XHidden string strip(s)
- Xstring s;
- X{
- X while (*s == ' ' || *s == '\t')
- X ++s;
- X return s;
- X}
- X
- XHidden string skip(s, pat)
- Xstring s, pat;
- X{
- X while (*s == *pat)
- X ++s, ++pat;
- X return s;
- X}
- X
- XHidden int /* initialise internal administration */
- Xstart_trm()
- X{
- X register int y;
- X
- X if (line == 0) {
- X if ((line = (char**) malloc(lines * sizeof(char*))) == NULL)
- X return TE_NOMEM;
- X for (y = 0; y < lines; y++) {
- X if ((line[y] = malloc(cols * sizeof(char))) == NULL)
- X return TE_NOMEM;
- X }
- X }
- X if (lenline == 0) {
- X if ((lenline = (intlet *)
- X malloc(lines * sizeof(intlet))) == NULL)
- X return TE_NOMEM;
- X }
- X
- X trmundefined();
- X return TE_OK;
- X}
- X
- X/*
- X * Termination call.
- X * Beware that it might be called by a catched interrupt even in the middle
- X * of trmstart()!
- X */
- X
- XVisible Procedure
- Xtrmend()
- X{
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmend();\n");
- X#endif
- X if (started && so_mode != Off)
- X standend();
- X if (scr_mode == ANSI) {
- X VOID fflush(stdout);
- X }
- X
- X started = No;
- X}
- X
- X/*
- X * Set all internal statuses to undefined, especially the contents of
- X * the screen, so a hard redraw will not be optimised to heaven.
- X */
- X
- XVisible Procedure
- Xtrmundefined()
- X{
- X register int y, x;
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmundefined();\n");
- X#endif
- X
- X cur_y = cur_x = Undefined;
- X so_mode = Undefined;
- X
- X for (y = 0; y < lines; y++) {
- X for (x = 0; x < cols; x++)
- X line[y][x] = ' ';
- X /* they may get printed in scrolling */
- X lenline[y] = 0;
- X }
- X}
- X
- X#ifdef DEBUG
- XHidden Procedure
- Xcheck_started(m)
- X char *m;
- X{
- X if (!started) {
- X printf("Not started: %s\n", m);
- X exit(TE_TWICE);
- X }
- X}
- X#else
- X#define check_started(m) /*empty*/
- X#endif
- X
- X/*
- X * Sensing the cursor.
- X * (NOT IMPLEMENTED, since there is no way to locally move the cursor.)
- X */
- X
- X/*
- X * Sense the current (y, x) cursor position, after a possible manual
- X * change by the user with local cursor motions.
- X * If the terminal cannot be asked for the current cursor position,
- X * or if the string returned by the terminal is garbled,
- X * the position is made Undefined.
- X */
- XVisible Procedure
- Xtrmsense(py, px)
- X int *py;
- X int *px;
- X{
- X/* bool getpos(); */
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmsense(&yy, &xx);\n");
- X#endif
- X check_started(MESS(7904, "trmsense called outside trmstart/trmend"));
- X
- X *py = *px = Undefined;
- X
- X/*
- X * if (flags&CAN_SENSE && getpos(py, px)) {
- X * if (*py < 0 || lines <= *py || *px < 0 || cols <= *px)
- X * *py = *px = Undefined;
- X * }
- X */
- X cur_y = *py;
- X cur_x = *px;
- X}
- X
- X/*
- X * Putting data on the screen.
- X */
- X
- X/*
- X * Fill screen area with given data.
- X * Characters with the SO-bit (0200) set are put in standout mode.
- X * (Unfortunately this makes it impossible to display accented characters.
- X * The interface should change.)
- X */
- XVisible Procedure
- Xtrmputdata(yfirst, ylast, indent, data)
- Xint yfirst;
- Xint ylast;
- Xregister int indent;
- Xregister string data;
- X{
- X register int y;
- X int x, len, lendata, space;
- X
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmputdata(%d, %d, %d, \"%s\");\n", yfirst, ylast, indent, data);
- X#endif
- X check_started(MESS(7905, "trmputdata called outside trmstart/trmend"));
- X
- X if (yfirst < 0)
- X yfirst = 0;
- X if (ylast >= lines)
- X ylast = lines-1;
- X space = cols*(ylast-yfirst+1) - indent;
- X if (space <= 0)
- X return;
- X yfirst += indent/cols;
- X indent %= cols;
- X y = yfirst;
- X if (data) {
- X x = indent;
- X lendata = strlen(data);
- X if (ylast == lines-1 && lendata >= space)
- X lendata = space - 1;
- X len = Min(lendata, cols-x);
- X while (y <= ylast) {
- X put_line(y, x, data, len);
- X y++;
- X lendata -= len;
- X if (lendata > 0) {
- X x = 0;
- X data += len;
- X len = Min(lendata, cols);
- X }
- X else
- X break;
- X }
- X }
- X if (y <= ylast)
- X clear_lines(y, ylast);
- X}
- X
- X/*
- X * We will try to get the picture:
- X *
- X * op>>>>>>>>>>>op oq
- X * ^ ^ ^
- X * <xskip><-----m1----><---------------od-------------------->
- X * OLD: "You're in a maze of twisty little pieces of code, all alike"
- X * NEW: "in a maze of little twisting pieces of code, all alike"
- X * <-----m1----><----------------nd--------------------->
- X * ^ ^ ^
- X * np>>>>>>>>>>>np nq
- X * where
- X * op, oq, np, nq are pointers to start and end of Old and New data,
- X * and
- X * xskip = length of indent to be skipped,
- X * m1 = length of Matching part at start,
- X * od = length of Differing end on screen,
- X * nd = length of Differing end in data to be put.
- X */
- XHidden int
- Xput_line(y, xskip, data, len)
- Xint y, xskip;
- Xstring data;
- Xint len;
- X{
- X register char *op, *oq, *np, *nq;
- X int m1, od, nd, delta;
- X
- X /* calculate the magic parameters */
- X op = &line[y][xskip];
- X oq = &line[y][lenline[y]-1];
- X np = data;
- X nq = data + len - 1;
- X m1 = 0;
- X while ((*op&SOCHAR) == (*np&SOCHAR) && op <= oq && np <= nq)
- X op++, np++, m1++;
- X od = oq - op + 1;
- X nd = nq - np + 1;
- X /* now we have the picture above */
- X
- X if (od==0 && nd==0)
- X return;
- X
- X delta = nd - od;
- X move(y, xskip + m1);
- X if (nd > 0) {
- X put_str(np, nd);
- X }
- X if (delta < 0) {
- X clr_to_eol();
- X return;
- X }
- X lenline[y] = xskip + len;
- X if (cur_x == cols) {
- X cur_y++;
- X cur_x = 0;
- X }
- X}
- X
- X/*
- X * Scrolling (part of) the screen up (or down, dy<0).
- X */
- X
- XVisible Procedure
- Xtrmscrollup(yfirst, ylast, by)
- Xregister int yfirst;
- Xregister int ylast;
- Xregister int by;
- X{
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmscrollup(%d, %d, %d);\n", yfirst, ylast, by);
- X#endif
- X check_started(MESS(7906, "trmscrollup called outside trmstart/trmend"));
- X
- X if (by == 0)
- X return;
- X
- X if (yfirst < 0)
- X yfirst = 0;
- X if (ylast >= lines)
- X ylast = lines-1;
- X
- X if (yfirst > ylast)
- X return;
- X
- X if (so_mode != Off)
- X standend();
- X
- X if (by > 0 && yfirst + by > ylast
- X ||
- X by < 0 && yfirst - by > ylast)
- X {
- X clear_lines(yfirst, ylast);
- X return;
- X }
- X
- X switch (scr_mode) {
- X case BIOS:
- X biosscrollup(yfirst, ylast, by);
- X break;
- X case ANSI:
- X if (by > 0 && yfirst == 0) {
- X lf_scroll(ylast, by);
- X }
- X else if (by > 0) {
- X move_lines(yfirst+by, yfirst, ylast-yfirst+1-by, 1);
- X clear_lines(ylast-by+1, ylast);
- X }
- X else {
- X move_lines(ylast+by, ylast, ylast-yfirst+1+by, -1);
- X clear_lines(yfirst, yfirst-by-1);
- X }
- X break;
- X }
- X}
- X
- X/*
- X * Synchronization, move cursor to given position (or previous if < 0).
- X */
- X
- XVisible Procedure
- Xtrmsync(y, x)
- X int y;
- X int x;
- X{
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmsync(%d, %d);\n", y, x);
- X#endif
- X check_started(MESS(7907, "trmsync called outside trmstart/trmend"));
- X
- X if (0 <= y && y < lines && 0 <= x && x < cols) {
- X move(y, x);
- X }
- X VOID fflush(stdout);
- X}
- X
- X/*
- X * Send a bell, visible if possible.
- X */
- X
- XVisible Procedure
- Xtrmbell()
- X{
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmbell();\n");
- X#endif
- X check_started(MESS(7908, "trmbell called outside trmstart/trmend"));
- X ring_bell();
- X}
- X
- X/*
- X * Now for the real work: here are all low level routines that really
- X * differ for BIOS or ANSI mode.
- X */
- X
- X/*
- X * BIOS video io is called by generating an 8086 software interrupt,
- X * using lattice's int86() function.
- X * To ease coding, all routines fill in the apropriate parameters in regs,
- X * and than call bios10(code), where code is to be placed in ah.
- X */
- X
- XHidden union REGS regs, outregs;
- X
- X/* A macro for speed */
- X#define bios10(code) (regs.h.ah = (code), int86(0x10, ®s, ®s))
- X#define nbios10(code) (regs.h.ah = (code), int86(0x10, ®s, &outregs))
- X
- X/* Video attributes: (see the BASIC manual) (used for standout mode) */
- X
- XHidden int video_attr;
- X#ifndef GFX
- X#define V_NORMAL 7
- X#else
- X#define V_NORMAL (gfx_mode == TEXT_MODE ? 7 : 0)
- X#endif
- X#define V_STANDOUT (7<<4)
- X
- X/* Some BIOS only routines */
- X
- XHidden get_cols()
- X{
- X bios10(15);
- X return regs.h.ah;
- X}
- X
- X/*
- X * ANSI escape sequences
- X */
- X#define A_CUP "\033[%d;%dH" /* cursor position */
- X#define A_SGR0 "\033[0m" /* set graphics rendition to normal */
- X#define A_SGR7 "\033[7m" /* set graphics rendition to standout */
- X#define A_ED "\033[2J" /* erase display (and cursor home) */
- X#define A_EL "\033[K" /* erase (to end of) line */
- X
- X/*
- X * The following routine is the time bottleneck, I believe!
- X */
- X
- XHidden Procedure
- Xput_str(data, n)
- Xchar *data;
- Xint n;
- X{
- X register char c, so;
- X
- X so = so_mode;
- X if (scr_mode == BIOS) {
- X regs.x.cx = 1; /* repition count */
- X regs.h.bh = 0; /* page number */
- X regs.h.bl = video_attr;
- X while (--n >= 0) {
- X c = (*data++)&SOCHAR;
- X if ((c&SOBIT) != so) {
- X so = c&SOBIT;
- X so ? standout() : standend();
- X regs.h.bl = video_attr;
- X }
- X regs.h.al = c&CHAR;
- X nbios10(9);
- X if (cur_x >= cols-1) {
- X line[cur_y][cols-1] = c;
- X continue;
- X }
- X regs.h.dh = cur_y;
- X regs.h.dl = cur_x + 1;
- X nbios10(2);
- X line[cur_y][cur_x] = c;
- X cur_x++;
- X }
- X }
- X else {
- X while (--n >= 0) {
- X c = (*data++)&SOCHAR;
- X if ((c&SOBIT) != so) {
- X so = c&SOBIT;
- X so ? standout() : standend();
- X }
- X putch(c&CHAR);
- X line[cur_y][cur_x] = c;
- X cur_x++;
- X }
- X }
- X}
- X
- X/*
- X * Move to position y,x on the screen
- X */
- X
- XHidden Procedure
- Xmove(y, x)
- Xint y, x;
- X{
- X if (scr_mode != BIOS && cur_y == y && cur_x == x)
- X return;
- X switch (scr_mode) {
- X case BIOS:
- X regs.h.dh = y;
- X regs.h.dl = x;
- X regs.h.bh = 0; /* Page; must be 0 for graphics */
- X bios10(2);
- X break;
- X case ANSI:
- X cprintf(A_CUP, y+1, x+1);
- X break;
- X }
- X cur_y = y;
- X cur_x = x;
- X}
- X
- XHidden Procedure
- Xstandout()
- X{
- X so_mode = On;
- X switch (scr_mode) {
- X case BIOS:
- X video_attr = V_STANDOUT;
- X break;
- X case ANSI:
- X cputs(A_SGR7);
- X break;
- X }
- X}
- X
- XHidden Procedure
- Xstandend()
- X{
- X so_mode = Off;
- X switch (scr_mode) {
- X case BIOS:
- X video_attr = V_NORMAL;
- X break;
- X case ANSI:
- X cputs(A_SGR0);
- X break;
- X }
- X}
- X
- X#ifdef UNUSED
- XHidden Procedure
- Xput_c(c)
- Xint c;
- X{
- X int ch;
- X
- X ch = c&CHAR;
- X#ifndef NDEBUG
- X if (!isprint(ch)) {
- X ch = '?';
- X c = (c&SOBIT)|'?';
- X }
- X#endif
- X switch (scr_mode) {
- X case BIOS:
- X regs.h.al = ch;
- X regs.h.bl = video_attr;
- X regs.x.cx = 1; /* repition count */
- X regs.h.bh = 0; /* page number */
- X bios10(9);
- X if (cur_x >= cols-1) {
- X line[cur_y][cols-1] = c;
- X return;
- X }
- X regs.h.dh = cur_y;
- X regs.h.dl = cur_x + 1;
- X bios10(2);
- X break;
- X case ANSI:
- X putch(ch);
- X break;
- X }
- X line[cur_y][cur_x] = c;
- X cur_x++;
- X}
- X#endif UNUSED
- X
- XHidden Procedure
- Xclear_lines(yfirst, ylast)
- Xint yfirst, ylast ;
- X{
- X register int y;
- X
- X if (scr_mode == BIOS) {
- X regs.h.al = 0; /* scroll with al = 0 means blank window */
- X regs.h.ch = yfirst;
- X regs.h.cl = 0;
- X regs.h.dh = ylast;
- X regs.h.dl = cols-1;
- X regs.h.bh = V_NORMAL;
- X bios10(6);
- X for (y = yfirst; y <= ylast; y++)
- X lenline[y] = 0;
- X return;
- X }
- X /* scr_mode == ANSI */
- X if (yfirst == 0 && ylast == lines-1) {
- X if (so_mode == On)
- X standend();
- X move(0, 0); /* since some ANSI'd don't move */
- X cputs(A_ED);
- X cur_y = cur_x = 0;
- X for (y = yfirst; y < ylast; y++)
- X lenline[y] = 0;
- X return;
- X }
- X for (y = yfirst; y <= ylast; y++) {
- X if (lenline[y] > 0) {
- X move(y, 0);
- X clr_to_eol();
- X }
- X }
- X}
- X
- XHidden Procedure
- Xclr_to_eol()
- X{
- X if (so_mode == On)
- X standend();
- X switch (scr_mode) {
- X case BIOS:
- X regs.h.bh = 0; /* page */
- X regs.x.cx = lenline[cur_y] - cur_x;
- X regs.h.al = ' ';
- X regs.h.bl = V_NORMAL;
- X bios10(9);
- X break;
- X case ANSI:
- X cputs(A_EL);
- X break;
- X }
- X lenline[cur_y] = cur_x;
- X}
- X
- XHidden Procedure /* scrolling for BIOS */
- Xbiosscrollup(yfirst, ylast, by)
- Xint yfirst;
- Xint ylast;
- Xint by;
- X{
- X regs.h.al = (by < 0 ? -by : by);
- X regs.h.ch = yfirst;
- X regs.h.cl = 0;
- X regs.h.dh = ylast;
- X regs.h.dl = cols-1;
- X regs.h.bh= V_NORMAL;
- X bios10(by < 0 ? 7 : 6);
- X cur_y = cur_x = Undefined;
- X if (by > 0)
- X scr_lines(yfirst, ylast, by, 1);
- X else
- X scr_lines(ylast, yfirst, -by, -1);
- X}
- X
- XHidden Procedure /* Reset internal administration accordingly */
- Xscr_lines(yfrom, yto, n, dy)
- Xint yfrom, yto, n, dy;
- X{
- X register int y, x;
- X char *saveln;
- X
- X while (n-- > 0) {
- X saveln = line[yfrom];
- X for (y = yfrom; y != yto; y += dy) {
- X line[y] = line[y+dy];
- X lenline[y] = lenline[y+dy];
- X }
- X line[yto] = saveln;
- X for (x = 0; x < cols; x++ )
- X line[yto][x] = ' ';
- X lenline[yto] = 0;
- X }
- X}
- X
- XHidden Procedure
- Xlf_scroll(yto, by)
- Xint yto;
- Xint by;
- X{
- X register int n = by;
- X
- X move(lines-1, 0);
- X while (n-- > 0) {
- X putch('\n');
- X }
- X scr_lines(0, lines-1, by, 1);
- X move_lines(lines-1-by, lines-1, lines-1-yto, -1);
- X clear_lines(yto-by+1, yto);
- X}
- X
- XHidden Procedure /* for dumb scrolling, uses and updates */
- Xmove_lines(yfrom, yto, n, dy) /* internal administration */
- Xint yfrom;
- Xint yto;
- Xint n;
- Xint dy;
- X{
- X while (n-- > 0) {
- X put_line(yto, 0, line[yfrom], lenline[yfrom]);
- X yfrom += dy;
- X yto += dy;
- X }
- X}
- X
- XHidden Procedure ring_bell()
- X{
- X switch (scr_mode) {
- X case BIOS:
- X regs.h.al = '\007';
- X regs.h.bl = V_NORMAL;
- X bios10(14);
- X break;
- X case ANSI:
- X putch('\007');
- X break;
- X }
- X}
- X
- X/*
- X * Show the current internal statuses of the screen on stderr.
- X * For debugging only.
- X */
- X
- X#ifdef SHOW
- XVisible Procedure
- Xtrmshow(s)
- Xchar *s;
- X{
- X int y, x;
- X
- X fprintf(stderr, "<<< %s >>>\n", s);
- X for (y = 0; y < lines; y++) {
- X for (x = 0; x <= lenline[y] /*** && x < cols ***/ ; x++) {
- X fputc(line[y][x]&CHAR, stderr);
- X }
- X fputc('\n', stderr);
- X for (x = 0; x <= lenline[y] && x < cols-1; x++) {
- X if (line[y][x]&SOBIT)
- X fputc('-', stderr);
- X else
- X fputc(' ', stderr);
- X }
- X fputc('\n', stderr);
- X }
- X fprintf(stderr, "CUR_Y = %d, CUR_X = %d.\n", cur_y, cur_x);
- X VOID fflush(stderr);
- X}
- X#endif
- X
- X/*
- X * Interrupt handling.
- X *
- X * (This has not properly been tested, nor is it clear that
- X * this interface is what we want. Anyway, it's here for you
- X * to experiment with. What does it do, you may ask?
- X * Assume an interactive program which reads its characters
- X * through trminput. Assume ^C is the interrupt character.
- X * Normally, ^C is treated just like any other character: when
- X * typed, it turns up in the input. The program may understand
- X * input ^C as "quit from the current mode".
- X * Occasionally, the program goes into a long period of computation.
- X * Now it would be uninterruptible, except if it calls trminterrupt
- X * at times in its computational loop. Trminterrupt magically looks
- X * ahead in the input queue, and if it sees a ^C, discards all input
- X * before that point and returns Yes. It also sets a flag, so that
- X * the interupt "sticks around" until either trminput or trmavail
- X * is called. It is undefined whether typing ^C several times in
- X * a row is seen as one interrupt, or an interrupt followed by input
- X * of ^C's. A program should be prepared for either.)
- X */
- X
- Xstatic bool intrflag= No;
- X
- Xstatic
- Xhandler(sig)
- X int sig;
- X{
- X signal(sig, handler);
- X intrflag= Yes;
- X}
- X
- Xstatic
- Xset_handler()
- X{
- X signal(SIGINT, handler);
- X}
- X
- Xbool
- Xtrminterrupt()
- X{
- X /* Force a check for Control-break which will call handler. */
- X kbhit();
- X return intrflag;
- X}
- X
- X/*
- X * Terminal input without echo.
- X * (This is a recent addition to this module, but will soon be standard).
- X */
- X
- Xtrminput()
- X{
- X intrflag= No;
- X return bdos(0x7, 0, 0) & 0377; /* Input, no echo, no ^C checks */
- X}
- X
- X/*
- X * Check for character available.
- X *
- X * To do this properly, should call DOS function 6,
- X * but the relevant bit (the Z flag) can't be checked from C.
- X * For now, say we don't know.
- X */
- X
- Xtrmavail()
- X{
- X intrflag= No;
- X return -1;
- X}
- X
- Xtrmsuspend()
- X{
- X /* Not implementable on MS-DOS */
- X}
- @//E*O*F p1trm.c//
- if test 21268 -ne "`wc -c <'p1trm.c'`"; then
- echo shar: error transmitting "'p1trm.c'" '(should have been 21268 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'trm.h'" '(879 characters)'
- if test -f 'trm.h' ; then
- echo shar: will not over-write existing file "'trm.h'"
- else
- sed 's/^X//' >trm.h <<'@//E*O*F trm.h//'
- X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
- X
- X/*
- X * Terminal capabilities. These correspond to bits set by trmstart in its
- X * parameter flags parameter.
- X */
- X
- X#define HAS_STANDOUT 1 /* Terminal has inverse video or underline */
- X#define CAN_SCROLL 2 /* Terminal can insert/delete lines */
- X#define CAN_OPTIMISE 4 /* Terminal can insert/delete characters */
- X#define CAN_SENSE 8 /* Terminal can send cursor position */
- X
- X/*
- X * Error codes returned by trmstart.
- X */
- X
- X#define TE_OK 0 /* No errors */
- X#define TE_TWICE 1 /* Trmstart called again */
- X#define TE_NOTERM 2 /* $TERM not set or empty */
- X#define TE_BADTERM 3 /* $TERM not found in termcap database */
- X#define TE_DUMB 4 /* Terminal too dumb */
- X#define TE_NOTTY 5 /* Stdout not a tty device */
- X#define TE_NOMEM 6 /* Can't get enough memory */
- X#define TE_OTHER 7 /* This and higher are reserved errors */
- @//E*O*F trm.h//
- if test 879 -ne "`wc -c <'trm.h'`"; then
- echo shar: error transmitting "'trm.h'" '(should have been 879 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'MANIFEST'" '(270 characters)'
- if test -f 'MANIFEST' ; then
- echo shar: will not over-write existing file "'MANIFEST'"
- else
- sed 's/^X//' >MANIFEST <<'@//E*O*F MANIFEST//'
- X File Name Kit # Description
- X-----------------------------------------------------------
- X MANIFEST 1 This shipping list
- X README 1
- X p1trm.c 1
- X trm.h 1
- X vtrm.c 2
- @//E*O*F MANIFEST//
- if test 270 -ne "`wc -c <'MANIFEST'`"; then
- echo shar: error transmitting "'MANIFEST'" '(should have been 270 characters)'
- fi
- fi # end of overwriting check
- echo shar: "End of archive 1 (of 2)."
- cp /dev/null ark1isdone
- DONE=true
- for I in 1 2; do
- if test -! f ark${I}isdone; then
- echo "You still need to run archive ${I}."
- DONE=false
- fi
- done
- case $DONE in
- true)
- echo "You have run all 2 archives."
- echo 'Now see the README'
- ;;
- esac
- ## End of shell archive.
- exit 0
-